package m.fun.service;

import m.appserver.AuthInfoUtil;
import m.base.model.StoreInfo;
import m.base.model.UserInfo;
import m.base.util.PowerUtil;
import m.common.model.util.*;
import m.common.service.Service;
import m.fun.model.*;
import m.store.model.*;
import m.store.service.OrderRepositoryCheckService;
import m.store.service.SaleInfoService;
import m.store.service.StockInfoService;
import m.store.service.StoreNumberService;
import m.store.task.StoreGoodsSupport;
import m.system.db.TransactionManager;
import m.system.exception.MException;
import m.system.util.*;

import java.util.*;

public class CountInfoService extends Service {
    public String save(CountInfo model, List<CountDetail> goodsList) throws Exception {
        if(null==goodsList||goodsList.isEmpty()) throw new MException(this.getClass(),"请添加盘点明细");
        ModelQueryCheck.init(model)
            .checkNotNull("countDate","盘点日期不能为空")
            .checkNotNull("guest.oid","请选择客户")
            .checkNotNull("status","状态错误")
            .checkStrEq("status", OrderModel.Status_Register,"登记状态才能修改")
            .doCheck(false,true);
        PowerUtil.verifyAccountDate(model.getCountDate(),"盘点日期");
        String msg="";
        if(ObjectUtil.isEmptyOid(model)){
            model.setOid(GenerateID.generatePrimaryKey());
            ModelUpdateUtil.insertModel(model);
            msg="保存成功";
        }else{
            ModelUpdateUtil.updateModel(model,"guest.oid","countDate","remark");
            msg="修改成功";
        }
        ModelUpdateUtil.delete(CountDetail.class, QueryCondition.eq("count.oid",model.getOid()));
        Map<String,Integer> numMap=new HashMap<>();
        Set<String> error=new HashSet<>();
        for(CountDetail record : goodsList){
            ModelQueryCheck.init(record)
                .checkNotNull("record.oid","请选择盘点库存商品")
                .checkNotNull("num","请输入数量差值")
                .checkNotNull("price","请输入单价")
                .checkNotNull("preferential","请输入优惠金额")
                .doCheck(false,true);
            if(record.getNum()==0) throw new MException(this.getClass(),"请输入正确的数量差值（不为0）");
            GoodsStockRecord stockRecord=ModelQueryList.getModel(record.getRecord(),"*","goods.*");
            numMap.merge(stockRecord.getOid(), record.getNum(), Integer::sum);//累加相同商品数量
            if(stockRecord.getSurplusNum()+numMap.get(stockRecord.getOid())<0)
                error.add(stockRecord.getGoods().getName());
            record.setOid(GenerateID.generatePrimaryKey());
            record.setGoods(stockRecord.getGoods());
            record.setCount(model);
            record.setOperDate(new Date());
            record.setAmount(NumberUtil.round(record.getNum()*record.getPrice()-record.getPreferential(),2));
            record.setPreferentialPrice(NumberUtil.round((record.getNum()*record.getPrice()-record.getPreferential())/record.getNum(),2));
        }
        if(!error.isEmpty()) //存在库存不足
            throw new MException(this.getClass(),"库存不足 - "+ ArrayUtil.connection(error.toArray(),","));
        ModelUpdateUtil.insertModels(goodsList.toArray(new CountDetail[0]));
        updateAmount(model.getOid());
        return msg;
    }
    private void updateAmount(String oid) throws MException {
        ModelUpdate.init(CountInfo.class)
            .set("countAmount",CountDetail.class,"ifnull(sum(#{amount}),0)",QueryCondition.eq("count.oid",oid))
            .execute(oid);
    }

    /**
     * 提交
     */
    public void saveAndSubmit(CountInfo model, List<CountDetail> goodsList,boolean repositoryCheck) throws Exception {
        save(model,goodsList);
        model.setStatus(OrderModel.Status_Check);
        if(repositoryCheck) getService(OrderRepositoryCheckService.class).insertCheck(model);
        model.setSubmitDate(new Date());
        ModelUpdateUtil.updateModel(model,"status","submitDate");
    }
    public void saveAndSubmit(CountInfo model, List<CountDetail> goodsList) throws Exception {
        saveAndSubmit(model,goodsList,true);
    }

    /**
     * 删除
     */
    public void delete(String oid, UserInfo user) throws Exception {
        CountInfo model=ModelQueryList.getModel(CountInfo.class,oid,"*");
        ModelQueryCheck.init(model)
            .checkStrEq("status",OrderModel.Status_Register,"登记中才能删除")
            .checkStrEq("inputUser.oid",user.getOid(),"权限错误")
            .doCheck(false,true);
        ModelUpdateUtil.deleteModel(model);
        ModelUpdateUtil.delete(CountDetail.class, QueryCondition.eq("count.oid",model.getOid()));
    }

    /**
     * 审核通过
     */
    public void check(String oid, Date countDate, String remark, StoreInfo store, UserInfo user) throws Exception {
        getService(OrderRepositoryCheckService.class).verifyCheckOver(oid);
        CountInfo model=ModelQueryList.getModel(CountInfo.class,oid,"*");
        model.setCountDate(countDate);
        model.setRemark(remark);
        ModelQueryCheck.init(model)
            .checkNotNull("countDate","盘点日期不能为空")
            .checkStrEq("status",OrderModel.Status_Check,"审核中才能通过")
            .checkStrEq("store.oid",store.getOid(),"权限错误")
            .doCheck(false,true);
        PowerUtil.verifyAccountDate(model.getCountDate(),"盘点日期");
        saveStockAndSale(oid);
        model.setStatus(OrderModel.Status_Done);
        model.setBuildStatus(BuildOrderModel.Build_Done);
        model.setCheckUser(user);
        model.setCheckDate(new Date());
        ModelUpdateUtil.updateModel(model,"buildStatus","status","checkUser.oid","checkDate","countDate","remark");
    }
    private void saveStockAndSale(String oid) throws Exception {
        CountInfo model=ModelQueryList.getModel(CountInfo.class,oid,"*");
        List<CountDetail> recordList=ModelQueryList.getModelList(CountDetail.class,
            new String[]{"*","record.*"}, null,
            QueryCondition.eq("count.oid", model.getOid())
        );
        boolean outFlag=false,inFlag=false;
        for(CountDetail record : recordList){
            if(record.getNum()<0&&!outFlag) outFlag=true;
            else if(record.getNum()>0&&!inFlag) inFlag=true;
        }
        String[] goodsOids=new String[0];
        if(outFlag) {
            TransactionManager tm = new TransactionManager();
            try {
                tm.begin();
                //生成盘点出库
                if (ObjectUtil.isEmptyOid(model.getSale())) {
                    SaleInfo sale = new SaleInfo();
                    sale.setOrderNo(StoreNumberService.getNextSaleNumber(model.getStore().getOid()));
                    sale.setStore(model.getStore());
                    sale.setStatus(OrderModel.Status_Register);
                    sale.setType(SaleInfo.Type_Count);
                    sale.setInputDate(model.getInputDate());
                    sale.setInputUser(model.getInputUser());
                    sale.setSaleDate(model.getCountDate());
                    sale.setGuest(model.getGuest());
                    sale.setRemark(model.getRemark());
                    List<GoodsOutRecord> saleRecords = new ArrayList<>();
                    for (CountDetail item : recordList) {
                        if(item.getNum()<0) {
                            GoodsOutRecord record = new GoodsOutRecord();
                            record.setRecord(item.getRecord());
                            record.setNum(-item.getNum());
                            record.setPrice(item.getPrice());
                            record.setPreferential(item.getPreferential());
                            record.setRemark(item.getRemark());
                            saleRecords.add(record);
                        }
                    }
                    goodsOids = recordList.stream().map(item -> item.getGoods().getOid()).toArray(String[]::new);
                    getService(SaleInfoService.class).saveAndSubmit(sale, saleRecords,false);
                    getService(SaleInfoService.class).check(sale.getOid(), sale.getSaleDate(), sale.getRemark(), sale.getStore(), model.getCheckUser());
                    model.setSale(sale);
                    ModelUpdateUtil.updateModel(model, "sale.oid");
                }
                tm.commit();
            } catch (Exception e) {
                tm.rollback();
                e.printStackTrace();
                throw new MException(this.getClass(), "生成盘点出库失败:" + e.getMessage());
            }
            StoreGoodsSupport.doneHandler(goodsOids);
        }
        if(inFlag) {
            TransactionManager tm = new TransactionManager();
            try {
                tm.begin();
                //生成盘点入库
                if (ObjectUtil.isEmptyOid(model.getStock())) {
                    StockInfo stock = new StockInfo();
                    stock.setOrderNo(StoreNumberService.getNextStockNumber(model.getStore().getOid()));
                    stock.setStore(model.getStore());
                    stock.setStatus(OrderModel.Status_Register);
                    stock.setType(StockInfo.Type_Count);
                    stock.setInputDate(model.getInputDate());
                    stock.setInputUser(model.getInputUser());
                    stock.setStockDate(model.getCountDate());
                    stock.setGuest(model.getGuest());
                    stock.setRemark(model.getRemark());
                    List<GoodsStockRecord> stockRecords = new ArrayList<>();
                    for (CountDetail item : recordList) {
                        if(item.getNum()>0) {
                            GoodsStockRecord record = new GoodsStockRecord();
                            record.setRepository(item.getRecord().getRepository());
                            record.setGoods(item.getGoods());
                            record.setStockNum(item.getNum());
                            record.setPrice(item.getPrice());
                            record.setPreferential(item.getPreferential());
                            record.setRemark(item.getRemark());
                            stockRecords.add(record);
                        }
                    }
                    getService(StockInfoService.class).saveAndSubmit(stock, stockRecords,false);
                    getService(StockInfoService.class).check(stock.getOid(), stock.getStockDate(), stock.getRemark(), stock.getStore(), model.getCheckUser());
                    model.setStock(stock);
                    ModelUpdateUtil.updateModel(model, "stock.oid");
                }
                tm.commit();
            } catch (Exception e) {
                tm.rollback();
                throw new MException(this.getClass(), "生成盘点入库失败:" + e.getMessage());
            }
        }
    }

    /**
     * 退回
     */
    public void refund(String oid, StoreInfo store,UserInfo user) throws Exception {
        CountInfo model=ModelQueryList.getModel(CountInfo.class,oid,"*");
        ModelQueryCheck.init(model)
            .checkStrEq("status",OrderModel.Status_Check,"审核中才能退回")
            .checkStrEq("store.oid",store.getOid(),"权限错误")
            .doCheck(false,true);
        model.setStatus(OrderModel.Status_Register);
        model.setCheckUser(user);
        model.setCheckDate(new Date());
        model.setRepositoryStatus(StringUtil.isSpace(model.getRepositoryStatus())?null:OrderRepositoryCheck.Status_No);
        ModelUpdateUtil.updateModel(model,"status","checkUser.oid","checkDate","repositoryStatus");
    }
}
